﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Soundteller.AudioVisual.Services.Interfaces;
using Soundteller.Audio.Repositories.Interfaces;
using Soundteller.Visual.Model;
using Soundteller.Audio.Model;
using Soundteller.AudioVisual.Repositories.Interfaces;
using Soundteller.Visual.Repositories.Interfaces;
using Soundteller.AudioVisual.Model;

namespace Soundteller.AudioVisual.Services
{
    public class SoundtellerInitializer : ISoundtellerInitializer
    {
        private readonly ISongRepository _songRepository;
        private readonly IPadRepository _padRepository;
        private readonly IGraphicRepository _graphicRepository;

        public SoundtellerInitializer(ISongRepository songRepository, IPadRepository padRepository, IGraphicRepository graphicRepository)
        {
            if (songRepository == null) throw new ArgumentNullException("songRepository");
            if (padRepository == null) throw new ArgumentNullException("padRepository");
            if (graphicRepository == null) throw new ArgumentNullException("graphicRepository");

            _songRepository = songRepository;
            _padRepository = padRepository;
            _graphicRepository = graphicRepository;
        }

        public void Initialize(InitializeSoundtellerRequest request)
        {
            Debug.WriteLine("{0}.Initialize()", GetType());

            if (request == null) throw new ArgumentNullException("request");

            var activeSong = _songRepository.GetActiveSong();
            if (activeSong == null) 
                throw new InvalidOperationException("Cannot initialize pad surface, no active song found");

            var canvas = CreateCanvas(request);

            if (activeSong.Sounds.Any())
            {
                var pads = CreatePads(activeSong.Sounds, canvas);

                foreach (var pad in pads)
                {
                    _padRepository.Add(pad);
                    canvas.InnerGraphics.Add(pad.Graphic);
                }
            }

            _graphicRepository.Add(canvas);
        }

        private GraphicBase CreateCanvas(InitializeSoundtellerRequest request)
        {
            var canvas = new StoredGraphic
            {
                Name = "canvas",
                Categories = new List<string> { GraphicCategories.Soundteller },
                X = 1,
                Y = 1,
                Width = request.CanvasWidth,
                Height = request.CanvasHeight
            };

            return canvas;
        }

        private List<Pad> CreatePads(IEnumerable<Sound> sounds, GraphicBase canvas)
        {
            var xPadStep = (canvas.Width / sounds.Count());
            var yPadStep = (canvas.Height / sounds.Count());

            var xCurrent = 0;
            var yCurrent = 0;

            var pads = new List<Pad>();
            foreach (var sound in sounds)
            {
                var graphic = new StoredGraphic
                {
                    Name = "pad",
                    Categories = new List<string> { GraphicCategories.Soundteller, GraphicCategories.PAD },
                    X = xCurrent,
                    Y = yCurrent,
                    Width = xPadStep,
                    Height = yPadStep
                };

                pads.Add(new Pad
                {
                    Sound = sound,
                    Graphic = graphic
                });

                xCurrent += xPadStep;
                yCurrent += yPadStep;
            }

            return pads;
        }
    }
}